#Region "Imports"
Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Media
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Xml
Imports System.Globalization
#End Region
Public Class HourglassForm
#Region "SoundImports"
    'Import for sound API
    <DllImport("aygshell.dll")> _
    Private Shared Function SndOpen(ByVal pszSoundFile As String, ByRef phSound As IntPtr) As UInteger
    End Function
    <DllImport("aygshell.dll")> _
    Private Shared Function SndPlayAsync(ByVal hSound As IntPtr, ByVal dwFlags As UInteger) As UInteger
    End Function
    <DllImport("aygshell.dll")> _
    Private Shared Function SndClose(ByVal hSound As IntPtr) As UInteger
    End Function
    <DllImport("aygshell.dll")> _
    Private Shared Function SndStop(ByVal SoundScope As Integer, ByVal hSound As IntPtr) As UInteger
    End Function
    Private hSound As IntPtr = IntPtr.Zero
    Const SND_SCOPE_PROCESS As Integer = &H1
    'End Import
#End Region
#Region "Variables"
    Private mStartTime As System.DateTime
    Private mTime As System.DateTime
    Private mAlarmTime As System.DateTime
    Private mRemaining As TimeSpan
    Public Shared mSnoozeTime As System.DateTime
    Public mSnoozeRemaining As TimeSpan
    Private Shared AUDIO_FILE As String
#End Region
#Region "Powerstate"
    '
    ' This region defines the power states needed to make sure the alarm sounds if the phone is in sleep mode
    '
    <DllImport("coredll.dll", CharSet:=CharSet.Unicode)> _
    Private Shared Function PowerPolicyNotify(ByVal dwMessage As Integer, ByVal dwData As Integer) As Boolean
    End Function


    <DllImport("coredll.dll", SetLastError:=True)> _
    Private Shared Function SetSystemPowerState(ByVal psState As String, ByVal StateFlags As Integer, ByVal Options As Integer) As Integer
    End Function

    Public Enum PPN_Message

        PPN_REEVALUATESTATE = &H1

        PPN_POWERCHANGE = &H2

        PPN_SUSPENDKEYPRESSED = &H4

        PPN_SUSPENDKEYRELEASED = &H5

        PPN_APPBUTTONPRESSED = &H6

        PPN_POWERBUTTONPRESSED = PPN_SUSPENDKEYPRESSED

        PPN_UNATTENDEDMODE = &H3

        PPN_OEMBASE = &H10000

    End Enum

    Public Enum PowerState

        POWER_STATE_ON = &H10000

        POWER_STATE_OFF = &H20000

        POWER_STATE_CRITICAL = &H40000

        POWER_STATE_BOOT = &H80000

        POWER_STATE_IDLE = &H100000

        POWER_STATE_SUSPEND = &H200000

        POWER_STATE_UNATTENDED = &H400000

        POWER_STATE_RESET = &H800000

        POWER_STATE_USERIDLE = &H1000000

        POWER_STATE_PASSWORD = &H10000000

    End Enum

    Public Enum PowerRequirement

        POWER_NAME = &H1

        POWER_FORCE = &H1000

        POWER_DUMPDW = &H2000

    End Enum


#End Region
#Region "VariousFunctions"
    'Play the sound
    Private Sub Play()
        SndOpen(AUDIO_FILE, hSound)
        SndPlayAsync(hSound, 0)
    End Sub
    'On application close, sync the settings to the XML file
    Private Sub Hourglass_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
        settings.Sync()
    End Sub

    Private Sub Hourglass_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        settings.refresh()
        SetAlarmTime.Hours = settings.Hours
        SetAlarmTime.Minutes = settings.Minutes
        SetAlarmTime.Seconds = settings.Seconds
        If settings.alarmsound = "" Then
            AUDIO_FILE = "\Windows\Alarm5.wav"
            settings.alarmsound = AUDIO_FILE
        Else
            AUDIO_FILE = settings.alarmsound
        End If
    End Sub
    '
    'Stop function for the media player.
    '
    Private Sub [Stop]()
        SndClose(hSound)
        SndStop(SND_SCOPE_PROCESS, IntPtr.Zero)
    End Sub
    Private Sub SoundAlarm()
        SetVibrate(True)
        SetSystemPowerState(Nothing, CInt(PowerState.POWER_STATE_ON), CInt(PowerRequirement.POWER_FORCE))
        PowerPolicyNotify(CInt(PPN_Message.PPN_UNATTENDEDMODE), 0)
        If settings.LoopChecked = True Then
            LoopTimer.Enabled = True
        End If
        Play()
    End Sub
#End Region
#Region "Buttons"

    Private Sub cmdStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdStart.Click
        Select UCase(cmdStart.Text)
            Case "START"
                SetAlarmTime.Enabled = False
                cmdStart.Text = "Stop"
                Timer1.Enabled = True
                mStartTime = DateTime.Now
                mAlarmTime = DateTime.Now + New TimeSpan(SetAlarmTime.Hours, SetAlarmTime.Minutes, SetAlarmTime.Seconds)
                AlarmTimeText.Text = mAlarmTime.ToString("T")
                SetSystemPowerState(Nothing, CInt(PowerState.POWER_STATE_UNATTENDED), CInt(PowerRequirement.POWER_FORCE))
                PowerPolicyNotify(CInt(PPN_Message.PPN_UNATTENDEDMODE), -1)
            Case "STOP"
                SetAlarmTime.Enabled = True
                cmdStart.Text = "Start"
                Timer1.Enabled = False
                SetVibrate(False)
                PowerPolicyNotify(CInt(PPN_Message.PPN_UNATTENDEDMODE), 0)
                [Stop]()
                LoopTimer.Enabled = False
                SnoozeTimer.Enabled = False
        End Select
    End Sub
    Private Sub ChangeSettings_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChangeSettings.Click
        Dim SettingsForm As Form = New SettingsForm()
        SettingsForm.Show()
    End Sub
 

    Private Sub cmdAbout_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAbout.Click
        Dim AboutForm As Form = New AboutForm()
        AboutForm.Show()
    End Sub

    '
    'Reset the alarm information
    '
    Private Sub cmdReset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdReset.Click
        settings.Hours = 0
        settings.Minutes = 0
        settings.Seconds = 0
        settings.alarmsound = ""
    End Sub

    Private Sub cmdExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdExit.Click
        Close()
        PowerPolicyNotify(CInt(PPN_Message.PPN_UNATTENDEDMODE), -1)
    End Sub
#End Region

#Region "AlarmValues"
    '
    'Set the value in the settings for the alarm
    'After 3 years I am unsure why this is commented out, maybe not finished.
    '

    '    Private Sub HoursUpDown_ValueChanged_1(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '        settings.Hours = Convert.ToInt32(HoursUpDown.Value)
    '    End Sub

    '    Private Sub MinuteUpDown_ValueChanged_1(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '        settings.Minutes = Convert.ToInt32(MinuteUpDown.Value)
    '    End Sub

    '    Private Sub SecondsUpDown_ValueChanged_1(ByVal sender As System.Object, ByVal e As System.EventArgs)
    '        settings.Seconds = Convert.ToInt32(SecondsUpDown.Value)
    '    End Sub
#End Region
#Region "Timers"
    '
    'Timer that checks to see if the timespan between Now and the alarm time has reached 0.
    'If the timespan is 0 the alarm is triggered.
    '
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        mRemaining = -(DateTime.Now - mAlarmTime)
        TimeRemaining.Text = mRemaining.ToString()

        If DateTime.Now > mAlarmTime Then
            SoundAlarm()
            Timer1.Enabled = False
            SnoozeNoticeForm.ShowDialog()

        End If
    End Sub
    '
    'Timer for the current time being displayed.
    '
    Private Sub Refreshtimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Refreshtimer.Tick
        CurrentTime.Text = DateTime.Now.ToString("h:mm:ss tt", CultureInfo.InvariantCulture)
    End Sub

    '
    'Loops the audio if the alarm is not turned off by the user based on the interval set in the timer.
    'TODO: Set this value in the settings.
    '
    Private Sub LoopTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoopTimer.Tick
        Play()
    End Sub
    '
    'Timer for the snooze alarm setting
    'Unsure if the snooze feature is fully functional anymore
    '
    Private Sub SnoozeTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SnoozeTimer.Tick
        mSnoozeRemaining = -(DateTime.Now - mSnoozeTime)
        TimeRemaining.Text = mSnoozeRemaining.ToString()
        If Now > mSnoozeTime Then
            SoundAlarm()
            SnoozeTimer.Enabled = False
            SnoozeNoticeForm.ShowDialog()
        End If
    End Sub
#End Region
#Region "Vibrate"
    ' 
    ' Creates a structure that will define the values needed to access the vibration motor within the cell phone. 
    ' As of windows mobile 6 the Vibrate() function was deprecated and the motor feature is now located under the LED controller.
    '

    Private Structure NLED_SETTINGS_INFO
        Public LedNum As Integer 'Defines which LED index is to be accessed
        Public OffOnBlink As Integer 'Sets the state of the LED
        Public TotalCycleTime As Integer ' Sets the cycle time for blinking
        Public OnTime As Integer 'Sets how long the LED will be on during a cycle
        Public OffTime As Integer ' Sets how long the LED will be off during a cycle
        Public MetaCycleOn As Integer
        Public MetaCycleOff As Integer
    End Structure
    'Import the DLL that handles the LED controller
    <DllImport("Coredll")> _
    Private Shared Function NLedSetDevice(ByVal deviceId As Integer, ByRef info As NLED_SETTINGS_INFO) As Boolean
    End Function

    Private Shared Sub SetVibrate(ByVal state As Boolean)
        Dim info As New NLED_SETTINGS_INFO()
        'Vibration is on LED 1
        info.LedNum = 1
        info.OffOnBlink = If(state, 1, 0)
        NLedSetDevice(1, info)
    End Sub
#End Region


End Class